#!/usr/bin/perl

# Copyright (C) 2008-2013 Zentyal S.L.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2, as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

use strict;
use warnings;

use EBox;
use EBox::Ldap;
use EBox::Global;
use EBox::Sudo;
use EBox::SambaLdapUser;


use constant MIN_ELEMENTS_SID_WITH_DOMAIN => 7;

EBox::init();


my ($domainID) = @ARGV;
defined $domainID or
  die 'you must supply the wanted domain SID portion';


my $samba = EBox::Global->modInstance('samba');
$samba->stopService();


_setLocalSID($domainID);
_setDomainSID($domainID);
_removeSambaDomainName();
_removeSambaDomain();
_fixLdapSIDs($domainID);


$samba->restartService();


sub _setLocalSID
{
    my ($domainID) = @_;
    my $cmd = "net  SETLOCALSID $domainID";
    EBox::Sudo::root($cmd);
}


sub _setDomainSID
{
    my ($domainID) = @_;
    my $cmd = "net  SETDOMAINSID $domainID";
    EBox::Sudo::root($cmd);
}

# remove all attributes sambaDomainName. those attributes refer to the previous
# domain name and are recreated by samba start
sub _removeSambaDomainName
{
    my $smbldap = new EBox::SambaLdapUser;
    $smbldap->deleteSambaDomainNameAttrs();
}

# remove the sambaDomain objects, those objects are recreated correctly by the
# samba start
sub _removeSambaDomain
{
    my $smbldap = new EBox::SambaLdapUser;
    $smbldap->deleteSambaDomains();
}

# change all SIDs to refer to the new domain
sub _fixLdapSIDs
{
    my ($domainID) = @_;

    my $ldap = EBox::Ldap->instance();
    my @sidAttrs = ('sambaSID', 'sambaPrimaryGroupSID');

    my $sidFilter = '(|';
    foreach my $attr (@sidAttrs) {
        $sidFilter .= "($attr=*)";
    }
    $sidFilter .= ')';

    my $result = $ldap->search(
                               {
                                base => $ldap->dn(),
                                filter => $sidFilter,		     
                                scope => 'sub',
                                attrs => \@sidAttrs,
                               }
                              );

  
    foreach my $entry ($result->entries()) {
        my @attrs = $entry->attributes;

        my $changed = 0;
        foreach my $attr (@attrs) {
            my $oldSid = $entry->get_value($attr); 
            # we just use the first attr value
            # bz it must be only one, anyway if
            # we have multiple entries we don't
            # know what we must use to get the
            # old SID
            defined $oldSid or
                next;

            my $newSid = _newSID($oldSid, $domainID);
            defined $newSid
                or next;

            $entry->replace($attr => $newSid);
            $changed = 1;
        }

        if ($changed) {
            $entry->update($ldap->ldapCon);
        }

    }
}



sub _newSID
{
    my ($oldSid, $domainId) = @_;

    my @sidPortions = split '-', $oldSid;
    if (@sidPortions < MIN_ELEMENTS_SID_WITH_DOMAIN ) {# SID not contains domain 
                                                       # portion so there is no
                                                       # need of a new SID
        return undef;
    }

    my $RID = pop @sidPortions;
    
    my $newSid = "$domainId-$RID";
    return $newSid;
}


1;
